package com.globalwave.report.template.excel;

import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFComment;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.util.CellRangeAddress;
import org.apache.poi.ss.util.Region;

import com.globalwave.common.U;

public class Cell {
    private HSSFCell _cell;
	private Row parentRow ;
	private boolean isListCell ;
	private Map<String, Object> context ;
	private Cell next ;
	private String beanName ;
	private String propertyName ;
	private boolean isMerge = true ;
	private Map<String, String> params  ;
    
    public Cell(HSSFCell _cell, Row parentRow) {
    	this._cell = _cell ;
    	this.parentRow = parentRow ;
    	this.context = parentRow.getTemplate().getContext() ;
    }
    
    public void precompile() {
    	HSSFComment comment = _cell.getCellComment() ;
		if (comment == null) {
			return ;
		}
		
		comment.getString().clearFormatting() ;
		
		String paramsAsStr = comment.getString().getString() ;
		
		params = U.parseParams(paramsAsStr) ;
		
		String templateValue = params.get("p") ;
	
		if (templateValue != null){
			compileBean(templateValue) ;
		}
		
		_cell.removeCellComment();
    }

	public void compile() throws Exception {
		if (propertyName != null) {
		    compileProperty() ;
		}

    	if(_cell.getCellType() == HSSFCell.CELL_TYPE_FORMULA) {
    		_cell.setCellFormula(_cell.getCellFormula()) ;
    	}
	}
	
	public Row getParentRow() {
		return parentRow;
	}
	
	public void compileBean(String beanPropertyName) {
		
		String[] names = beanPropertyName.split("\\.") ;
		
		beanName = names[0] ;
		propertyName = names[1] ;
		
		isListCell = (context.get(beanName) instanceof List) ;
		
		if (isListCell) {
			parentRow.setListName(beanName) ;
			
			isMerge = (params.get("m") != null) ;
			if (isMerge){
				parentRow.setMergeStarting(params.get("m")) ;
			}
		}
	}

	public void compileProperty() throws Exception {
		if (isListCell) {

			HSSFCell pCell = getPreviewRowCell() ;
			if (isMerge) {
				if (parentRow.isMergeStarting()) {
					setValue(pCell, beanName + "$item", propertyName) ;
				} else if (parentRow.isMergeEnding()) {
					//pCell.getRow().removeCell(pCell) ;

					int firstRow = parentRow.getMergeStartRowNum() ;
                    int lastRow = _cell.getRow().getRowNum() - 1 ;
                    int firstCol = _cell.getColumnIndex();
                    int lastCol = firstCol ;
					
                    CellRangeAddress range = new CellRangeAddress(firstRow, lastRow, firstCol, lastCol) ;
                    _cell.getSheet().addMergedRegion(range);
				} else {
					//pCell.getRow().removeCell(pCell) ;
				}
			} else {
			    setValue(pCell, beanName + "$item", propertyName) ;
			}
			/*
			String value = BeanUtils.getProperty(context.get(beanName + "$item"), propertyName);
			Double dbValue = null ;
	    	if(_cell.getCellType() == HSSFCell.CELL_TYPE_NUMERIC) {
	    		try{
	    		    dbValue = Double.valueOf(value) ;
	    		} catch(Exception e) {}
	    	}
			if(isMerge) {
				//this._cell.getSheet().addMergedRegion(region)
				if (dbValue == null) { 
				    pCell.setCellValue(value) ;
				} else {
					pCell.setCellValue(dbValue) ;
				}
			} else {
				if (dbValue == null) { 
				    pCell.setCellValue(value) ;
				} else {
					pCell.setCellValue(dbValue) ;
				}
			}*/
		} else {
			//this._cell.setCellValue((String)BeanUtils.getProperty(context.get(beanName ), propertyName)) ;
			setValue(_cell, beanName, propertyName) ;
		}
	}
	
	private void setValue(HSSFCell cell, String beanName, String propertyName) {
		
		String value = null;
		try {
			value = BeanUtils.getProperty(context.get(beanName), propertyName);
		} catch(Exception e) {
			value = "N/A" ;
		}
		Double dbValue = null ;

    	if(_cell.getCellType() == HSSFCell.CELL_TYPE_NUMERIC) {
    		try{
    		    dbValue = Double.valueOf(value) ;
    		} catch(Exception e) {}
    	}
    	
		//this._cell.getSheet().addMergedRegion(region)
		if (dbValue == null) { 
			cell.setCellValue(value) ;
		} else {
			cell.setCellValue(dbValue) ;
		}
	}
	
	private HSSFCell getPreviewRowCell() {
		int rowNum = _cell.getRow().getRowNum() ;
		int colNum = _cell.getColumnIndex() ;
		HSSFRow nextRow = _cell.getSheet().getRow(rowNum - 1) ;
		if (nextRow == null) {
			return null ;
		}
		
		return nextRow.getCell(colNum) ;
	} 
	
	private HSSFCell getNextRowCell() {
		int rowNum = _cell.getRow().getRowNum() ;
		int colNum = _cell.getColumnIndex() ;
		HSSFRow nextRow = _cell.getSheet().getRow(rowNum + 1) ;
		if (nextRow == null) {
			return null ;
		}
		
		return nextRow.getCell(colNum) ;
	} 
	
	public Cell getNext() {
		return next;
	}
	
	public void setNext(Cell next) {
		this.next = next;
	}

	public boolean isListCell() {
		return isListCell;
	}
	public boolean isMerge() {
		return isMerge;
	}
	
	public void resetToNextRowCell() {
		this._cell = getNextRowCell();
	}
}
